package wpp.view;

import java.util.ArrayList;
import java.util.List;

import wpp.cfg.DataConfig;
import wpp.cfg.WPFileBean;

import javafx.animation.FadeTransitionBuilder;
import javafx.animation.ParallelTransition;
import javafx.animation.ParallelTransitionBuilder;
import javafx.animation.ScaleTransitionBuilder;
import javafx.animation.SequentialTransitionBuilder;
import javafx.animation.TranslateTransition;
import javafx.animation.TranslateTransitionBuilder;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.input.ScrollEvent;
import javafx.util.Duration;

public class LocalPreviewPane extends PreviewPane {

	private static final Double[] ANIMATED_LEFT_POS = new Double[] { -500.0, 235.0 };
	private static final Double[] ANIMATED_RIGHT_POS = new Double[] { 1700.0, 235.0 };
	private static final Double[] ANIMATED_LEFT_POS_FOR_NEW_WPP = new Double[] {0.0, -250.0};
	private static final Double[] ANIMATED_LEFT_POS_FOR_DROP_WPP = new Double[] {1700.0, 470.0};
	private static final Integer ANIMATED_DURATION_MILLIS = 500;
	
	private Integer currentImageShowIndex = 0;
	private Integer animatingNode = 0;

	public LocalPreviewPane() {				
		addControl();	
		addEvent();
	}
	
	public void addANewWPPreview() {
		if(currentImageShowIndex == 0 && animatingNode == 0) {
			WPFileBean wpFileBean = null;
			if(imageShowContainer.getChildren().size() != 0) {
				wpFileBean = ((SimpleImageView)imageShowContainer.getChildren().get(0)).getWpFileBean();
			}
			WPFileBean newWpFileBean = DataConfig.getAWpFileBeanAfter(wpFileBean);
			if(newWpFileBean != null) {
				SimpleImageView newImageView = loadImage(newWpFileBean, 
						ANIMATED_LEFT_POS_FOR_NEW_WPP[0], ANIMATED_LEFT_POS_FOR_NEW_WPP[1]);
				final ObservableList<Node> nodes = imageShowContainer.getChildren();
				nodes.add(0, newImageView);
				SequentialTransitionBuilder.create().children(
					TranslateTransitionBuilder.create().toX(POSS[0][0] - newImageView.getLayoutX())
						.toY(POSS[0][1] - newImageView.getLayoutY()).duration(Duration.millis(ANIMATED_DURATION_MILLIS + 200)).build(),
					ScaleTransitionBuilder.create().toX(1.2).toY(0.8).duration(Duration.millis(150)).build(),
					ParallelTransitionBuilder.create().children(
						ScaleTransitionBuilder.create().toX(1).toY(1).duration(Duration.millis(150)).build(),
						TranslateTransitionBuilder.create().toY(POSS[0][1] - 28 - newImageView.getLayoutY()).duration(Duration.millis(150)).build()
					).build(),
					TranslateTransitionBuilder.create().toY(POSS[0][1] - newImageView.getLayoutY()).duration(Duration.millis(150)).build()			
				).node(newImageView).build().play();				
				for(int i = 1; i < nodes.size(); i ++) {
					final Node node = nodes.get(i);
					Double[] nextPos = i == GRID_CAPACITY ? ANIMATED_LEFT_POS_FOR_DROP_WPP : POSS[i];
					TranslateTransition transition = TranslateTransitionBuilder.create()
						.node(node)
						.toX(nextPos[0] - node.getLayoutX())
						.toY(nextPos[1] - node.getLayoutY())
						.duration(Duration.millis(ANIMATED_DURATION_MILLIS))
						.build();
					if(i == GRID_CAPACITY) { //The last one
						transition.setOnFinished(new EventHandler<ActionEvent>() {
							@Override
							public void handle(ActionEvent arg0) {
								nodes.remove(node);
							}
						});
					}
					transition.play();
				}
			}
		}
	}
	
	private void addControl() {
		imageShowContainer.getChildren().addAll(loadImages(DataConfig.getLatestWpFileBeans(1, GRID_CAPACITY)));
	}
	
	private void addEvent() {
		this.setOnScroll(eventOnScroll());
	}	
	
	private void navigateGridPane(Integer step) {
		Integer newIndex = currentImageShowIndex + step;
		if(newIndex < 0 || step == 0) {
			return;
		}
		List<WPFileBean> wpFileBeans = DataConfig.
				getLatestWpFileBeans(newIndex * GRID_CAPACITY + 1, GRID_CAPACITY);
		if(wpFileBeans != null && wpFileBeans.size() > 0 && animatingNode == 0) {
			currentImageShowIndex = newIndex;
			Double[] currentToPos;
			Double[] nextFromPos;
			if(step > 0) {
				currentToPos = ANIMATED_LEFT_POS;
				nextFromPos = ANIMATED_RIGHT_POS;
			} else {
				currentToPos = ANIMATED_RIGHT_POS;
				nextFromPos = ANIMATED_LEFT_POS;				
			}
			List<SimpleImageView> newImageViews = loadImages(wpFileBeans);
			getChildren().add(imageShowContainerUpLayer);
			for(Node node : imageShowContainer.getChildren()) {
				ParallelTransition transition = ParallelTransitionBuilder.create()
					.node(node)
					.children(
						TranslateTransitionBuilder.create()
							.toX(currentToPos[0] - node.getLayoutX())
							.toY(currentToPos[1] - node.getLayoutY())
							.duration(Duration.millis(ANIMATED_DURATION_MILLIS))
							.build(),
						ScaleTransitionBuilder.create()
							.toX(0.4)
							.toY(0.4)
							.duration(Duration.millis(ANIMATED_DURATION_MILLIS))
							.build(),
						FadeTransitionBuilder.create()
							.toValue(0.1)
							.duration(Duration.millis(ANIMATED_DURATION_MILLIS))
							.build()
					).build();
				transition.setOnFinished(eventOnImageDisappeared(node));
				transition.play();
				animatingNode ++;
			}
			for(int i = 0; i < newImageViews.size(); i++) {
				SimpleImageView imageView = newImageViews.get(i);
				imageView.setLayoutX(nextFromPos[0]);
				imageView.setLayoutY(nextFromPos[1]);
				imageShowContainer.getChildren().add(imageView);
				ParallelTransition transition = ParallelTransitionBuilder.create()
					.node(imageView)
					.children(
						TranslateTransitionBuilder.create()
							.toX(POSS[i][0] - imageView.getLayoutX())
							.toY(POSS[i][1] - imageView.getLayoutY())
							.duration(Duration.millis(ANIMATED_DURATION_MILLIS))
							.build(),
						ScaleTransitionBuilder.create()
							.fromX(0.4)
							.fromY(0.4)
							.toX(1)
							.toY(1)
							.duration(Duration.millis(ANIMATED_DURATION_MILLIS))
							.build(),
						FadeTransitionBuilder.create()
							.fromValue(0.1)
							.toValue(1)
							.duration(Duration.millis(ANIMATED_DURATION_MILLIS))
							.build()
					).build();
				transition.setOnFinished(eventOnImageAppeared(imageView));
				transition.play();		
				animatingNode ++;
			}			
		}		
	}
	
	private List<SimpleImageView> loadImages(List<WPFileBean> beans) {
		List<SimpleImageView> imageViews = new ArrayList<SimpleImageView>();
		for(int i = 0; i < beans.size(); i++) {
			imageViews.add(loadImage(beans.get(i), POSS[i][0], POSS[i][1]));
		}
		return imageViews;
	}	
	
	private SimpleImageView loadImage(WPFileBean bean, Double layoutX, Double layoutY) {
		SimpleImageView imageView = new SimpleImageView(bean);
		imageView.setLayoutX(layoutX);
		imageView.setLayoutY(layoutY);
		return imageView;
	}
	
	private void nodeAnimateStop() {
		animatingNode --;
		if(animatingNode == 0) {
			getChildren().remove(imageShowContainerUpLayer);
		}
	}

	//Event
	private EventHandler<ScrollEvent> eventOnScroll() {
		return new EventHandler<ScrollEvent>() {
			@Override
			public void handle(ScrollEvent ev) {				
				if(ev.getDeltaY() > 0) {					
					navigateGridPane(-1);
				} else if(ev.getDeltaY() < 0) {
					navigateGridPane(1);
				}					
			}			
		};
	}
	
	private EventHandler<ActionEvent> eventOnImageDisappeared(final Node node) {
		return new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent arg0) {
				imageShowContainer.getChildren().remove(node);
				nodeAnimateStop();
			}
		};
	}
	
	private EventHandler<ActionEvent> eventOnImageAppeared(final Node node) {
		return new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent arg0) {
				nodeAnimateStop();
			}
		};
	}
	
}
